package com.li.Demo;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;

/**  
 * 类说明   
 *  
 * @author ****  
 * @date 2018年3月19日  新建  
 */
public class NioClient {
	public static void main(String[] args) throws UnknownHostException, IOException {
		ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
		ByteBuffer readBuffer = ByteBuffer.allocate(1024);

		// 打开socket通道  
		SocketChannel sc = SocketChannel.open(); 
		//设置为非阻塞
		sc.configureBlocking(false); 
		//连接服务器地址和端口
		sc.connect(new InetSocketAddress("localhost", 8001)); 
		//打开选择器
		Selector selector = Selector.open(); 
		//注册连接服务器socket的动作
		sc.register(selector, SelectionKey.OP_CONNECT); 

		Scanner scanner = new Scanner(System.in); 
		while (true) {
			//选择一组键，其相应的通道已为 I/O 操作准备就绪。  
			//此方法执行处于阻塞模式的选择操作。
			selector.select();
			//返回此选择器的已选择键集。
			Set<SelectionKey> keys = selector.selectedKeys(); 
			Iterator<SelectionKey> keyIterator = keys.iterator(); 
			while (keyIterator.hasNext()) {
				SelectionKey key = keyIterator.next();
				keyIterator.remove(); 
				// 判断此通道上是否正在进行连接操作。 
				if (key.isConnectable()) {
					System.out.println("server connected...");
					SocketChannel channel = (SocketChannel) key.channel();
					if(channel.isConnectionPending()){    
                        channel.finishConnect();                              
                    }    
					// 设置成非阻塞    
//                    channel.configureBlocking(false);    
//                    //在这里可以给服务端发送信息哦    
//                    channel.write(ByteBuffer.wrap(new String("向服务端发送了一条信息").getBytes("utf-8")));    
//                    //在和服务端连接成功之后，为了可以接收到服务端的信息，需要给通道设置读的权限。    
                    channel.register(selector, SelectionKey.OP_WRITE);// 获得了可读的事件    
				} else if (key.isWritable()) { //写数据 
					System.out.print("please input message:"); 
					String message = "test"; 
					//ByteBuffer writeBuffer = ByteBuffer.wrap(message.getBytes()); 
					writeBuffer.clear();
					writeBuffer.put(message.getBytes());
					//将缓冲区各标志复位,因为向里面put了数据标志被改变要想从中读取数据发向服务器,就要复位
					writeBuffer.flip();
					sc.write(writeBuffer); 

					//注册写操作,每个chanel只能注册一个操作，最后注册的一个生效
					//如果你对不止一种事件感兴趣，那么可以用“位或”操作符将常量连接起来
					//int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;
					//使用interest集合
					sc.register(selector, SelectionKey.OP_READ);
				} else if (key.isReadable()){//读取数据
					System.out.print("receive message:");
					SocketChannel client = (SocketChannel) key.channel();
					//将缓冲区清空以备下次读取 
					readBuffer.clear();
					int num = client.read(readBuffer);
					System.out.println(new String(readBuffer.array(),0, num));
					//注册读操作，下一次读取
					sc.register(selector, SelectionKey.OP_WRITE);
				}
			} 
		}

	}
}
